/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package testalgorithm;



/**
 *
 * @author haoliang.donghl
 */
public class BagAlgorithm extends AbstractAlgorithm{
 
    public static void main(String[] args) {
        int cost;
        int ret;
        
        if (args.length > 0) {
            DICTIONARY_NAME = args[0];
        }
        readParameter(DICTIONARY_NAME + "\\info.txt");
        
        matrixIn = new int[NUM_APP][NUM_MACHINE];
        matrixOut = new int[NUM_APP][NUM_MACHINE];
        matrixCost = new int[NUM_APP][NUM_MACHINE];
        matrixState = new float[NUM_APP][NUM_MACHINE];
        vectorAppSize = new int[NUM_APP];
        vectorAppCPU = new float[NUM_APP];
        vectorMachineCPU = new float[NUM_MACHINE];

        readFromFile(DICTIONARY_NAME);

        printAppNeeds();
        checkConstraint(matrixIn);
        printMachineCPU();
        copyArray(matrixOut, matrixIn);
        calculateMatrixCost(matrixOut);

        //System.out.println("===================================");

        while ((ret = checkConstraint(matrixOut)) != -1){
            doAssign(ret);
        }
        printMachineCPU();

        cost = calculateCost();
        printMatrixInOut(matrixOut, DICTIONARY_NAME + "\\out.txt");
        //System.out.print("The Cost is ");
        //System.out.println(cost);

    }

    private static void doAssign(int p) {
        float[] values = new float[NUM_APP];
        float[] sizes = new float[NUM_APP];
        int[] assigns = new int[NUM_MACHINE];
        for (int i = 0; i < NUM_APP; i++){
            getMinValue(i, p, sizes , values, assigns);
        }
        chooseMinAndAssign(sizes, values, p);
    }

    private static void getMinValue(int app, int machine, float[] sizes,
                                       float[] values, int[] assigns) {
        float size = 0;
        float value = 0;
        float minCPU = Float.MAX_VALUE;
        int minID = 0;
        if (matrixOut[app][machine] != 2){
            value = Float.MAX_VALUE;
            size = 1;
        }else{
            for (int i = 0; i < NUM_MACHINE; i++){
                assigns[i] = matrixOut[app][i];
                if (assigns[i] != 2){
                    /*
                    if (minCPU > vectorMachineCPU[i]){
                        minCPU = vectorMachineCPU[i];
                        minID = i;
                    }
                     */
                    if (minCPU > matrixCost[app][i]
                        && vectorMachineCPU[i] + matrixState[app][machine] < CPU_UP_BOUND){
                        minCPU = matrixCost[app][i];
                        minID = i;
                    }
                }
            }
            if (minCPU < Float.MAX_VALUE){
                assigns[minID] = 2;
                if (vectorAppCPU[app] > PER_CPU_BOUND){
                    assigns[machine] = 2;
                }else{
                    assigns[machine] = 0;
                }
                size = matrixState[app][machine];
                value = matrixCost[app][minID];
            }else{
                value = Float.MAX_VALUE;
                size = 1;
            }
        }

        sizes[app] = size;
        values[app] = value;
        return;
    }

    private static void chooseMinAndAssign(float[] sizes, float[] values, int p){
        float[] density = new float[NUM_APP];
        float minValue = Float.MAX_VALUE;
        int minID = 0;
        int[] assigns = new int[NUM_MACHINE];
        for (int i = 0; i < NUM_APP; i++){
            density[i] = values[i] / sizes[i];
            if (minValue > density[i]){
                minValue = density[i];
                minID = i;
            }
        }
        getMinValue(minID, p, sizes, values, assigns);
        for (int j = 0; j < NUM_MACHINE; j++){
            matrixOut[minID][j] = assigns[j];
        }
    }
}
